package design.donkey.auto.ddl.util;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;

import design.donkey.framework.common.util.CommonUtils;

/**
 * AutoDdlCommonUtils
 *
 * @author zhangjiakung
 * @since 0.0.1
 */
public final class AutoDdlCommonUtils {

    /**
     * 下划线
     */
    public static final String UNDERLINE = "_";

    /**
     * 判断是否为其子集（忽略大小写）
     *
     * @param list 查找容器
     * @param value 查找对象
     * @return true 存在
     */
    public static boolean containsIgnoreCase(List<String> list, String value) {
        if (CommonUtils.isEmpty(list)) {
            return false;
        }
        for (String data : list) {
            if (CommonUtils.equalsIgnoreCase(data, value)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断两个字符串 是否完成不相等
     *
     * @param theList theList
     * @param thatList thatList
     * @return true 表示取值范围不同
     */
    public static boolean noEquals(List<String> theList, List<String> thatList) {
        return !equals(theList, thatList);
    }

    /**
     * 判断两个字符串 是否完成相等
     *
     * @param theList theList
     * @param thatList thatList
     * @return true 表示取值范围不同
     */
    public static boolean equals(List<String> theList, List<String> thatList) {
        if (thatList == null || theList == null) {
            return Objects.equals(thatList, theList);
        }
        if (!Objects.equals(theList.size(), thatList.size())) {
            return false;
        }
        for (int i = 0; i < theList.size(); i++) {
            if (!Objects.equals(theList.get(i), thatList.get(i))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 获取 注解
     *
     * @param annotatedElement 注解元素
     * @param annotationType 注解类型
     * @return null 注解不存在
     * @param <T> 注解返回类型
     */
    public static <T extends Annotation> T getAnnotation(AnnotatedElement annotatedElement, Class<T> annotationType) {
        if (annotatedElement == null) {
            return null;
        }
        return annotatedElement.getAnnotation(annotationType);
    }

    /**
     * getter 方法 is 前缀
     */
    public static final String GETTER_PREFIX_IS = "is";

    /**
     * getter 方法 get 前缀
     */
    public static final String GETTER_PREFIX = "get";

    /**
     * setter 方法 set 前缀
     */
    public static final String SETTER_PREFIX = "set";

    /**
     * 获取 getter 方法
     *
     * @param entityType 实体类型
     * @param fieldName 字段名称
     * @param fieldType 字段类型
     * @return null 表示不存在 getter 方法，存在返回 getter {@link Method}
     */
    public static Method setter(Class<?> entityType, String fieldName, Class<?> fieldType) {
        boolean isPrefix = (boolean.class.equals(fieldType) || Boolean.class.equals(fieldType))
            && fieldName.startsWith(GETTER_PREFIX_IS);
        if (isPrefix) {
            String setterName = SETTER_PREFIX + CommonUtils.removePrefix(fieldName, GETTER_PREFIX_IS);
            try {
                return entityType.getMethod(setterName, fieldType);
            } catch (Exception ignore) {
                // ignore
            }
        }
        try {
            String setterName = SETTER_PREFIX + CommonUtils.upperFirst(fieldName);
            Method method = entityType.getMethod(setterName, fieldType);
            // 校验返回类型
            return void.class.equals(method.getReturnType()) ? method : null;
        } catch (NoSuchMethodException ignore) {
            // 没有找打 getter 方法 返回 null
            return null;
        }
    }

    /**
     * 获取 getter 方法
     *
     * @param entityType 实体类型
     * @param fieldName 字段名称
     * @param fieldType 字段类型
     * @return null 表示不存在 getter 方法，存在返回 getter {@link Method}
     */
    public static Method getter(Class<?> entityType, String fieldName, Class<?> fieldType) {
        Method getter = getterNotCheckReturnType(entityType, fieldName, fieldType);
        if (getter == null) {
            return null;
        }
        return fieldType.equals(getter.getReturnType()) ? getter : null;
    }

    /**
     * 获取 getter 方法,不校验返回值
     *
     * @param entityType 实体类型
     * @param fieldName 字段名称
     * @param fieldType 字段类型
     * @return null 表示不存在 getter 方法，存在返回 getter {@link Method}
     */
    private static Method getterNotCheckReturnType(Class<?> entityType, String fieldName, Class<?> fieldType) {
        if (boolean.class.equals(fieldType) || Boolean.class.equals(fieldType)) {
            if (fieldName.startsWith(GETTER_PREFIX_IS)) {
                try {
                    return entityType.getMethod(fieldName);
                } catch (NoSuchMethodException ignore) {
                    // ignore
                }
            } else {
                String getterName = GETTER_PREFIX_IS + CommonUtils.upperFirst(fieldName);
                try {
                    return entityType.getMethod(getterName);
                } catch (NoSuchMethodException ignore) {
                    // ignore
                }
            }
        }
        try {
            String getterName = GETTER_PREFIX + CommonUtils.upperFirst(fieldName);
            return entityType.getMethod(getterName);
        } catch (NoSuchMethodException ignore) {
            // 没有找打 getter 方法 返回 null
            return null;
        }
    }

    /**
     * 是否存在某个类
     * 
     * @param className className
     * @return 是否存在
     */
    public static boolean existClass(String className) {
        try {
            Class.forName(className);
            return true;
        } catch (ClassNotFoundException e) {
            return false;
        }
    }

    private AutoDdlCommonUtils() {
        throw new IllegalStateException(AutoDdlCommonUtils.class + "不允许实例化");
    }
}
